

#include "SSF33Test.h"
#include "Common.h"

#define DATA_SIZE 32
#define BLOCK_SIZE 20
#define DEC_BLOCK_SIZE 16

Ssf33Test::Ssf33Test() { m_hKey = 0; }

Ssf33Test::~Ssf33Test() {}

void Ssf33Test::Test() {
  GenerateKey();
  if (m_hKey == 0) {
    return;
  }
  crypt_Single();
  crypt_Update();
}
void Ssf33Test::GenerateKey() {
  do {
    SHOW_INFO("Generate Ssf33 key to test...");
    CK_OBJECT_CLASS oClass = CKO_SECRET_KEY;
    CK_KEY_TYPE keyType = CKK_SSF33;
    CK_BBOOL bTrue = true;
    CK_BBOOL bFalse = false;
    CK_ULONG ulLen = 16;
    CK_MECHANISM mechanism = {CKM_SSF33_KEY_GEN, NULL_PTR, 0};
    CK_ATTRIBUTE Ssf33tem[] = {{CKA_CLASS, &oClass, sizeof(CK_OBJECT_CLASS)},
                               {CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)},
                               {CKA_TOKEN, &bFalse, sizeof(CK_BBOOL)},
                               {CKA_PRIVATE, &bTrue, sizeof(CK_BBOOL)},
                               {CKA_ENCRYPT, &bTrue, sizeof(CK_BBOOL)},
                               {CKA_DECRYPT, &bTrue, sizeof(CK_BBOOL)},
                               {CKA_VALUE_LEN, &ulLen, sizeof(CK_ULONG)}, };
    CK_ULONG ulCount = sizeof(Ssf33tem) / sizeof(CK_ATTRIBUTE);
    // generate key:
    START_OP("generate SSF33 key...")
    CK_RV rv = m_gToken->C_GenerateKey(hSession, &mechanism, Ssf33tem, ulCount,
                                       &m_hKey);
    CHECK_OP(rv)
  } while (0);
}
void Ssf33Test::crypt_Single() {
  const CK_ULONG DATA_LENGTH = 1024 * 3;
  CK_BYTE bIn[DATA_LENGTH] = {0}, bTemp[DATA_LENGTH] = {0},
          bOut[DATA_LENGTH] = {0};
  CK_ULONG ulIn = 0, ulOut = 0, ulTemp = 0;
  CK_ULONG Mechanism[3] = {CKM_SSF33_CBC, CKM_SSF33_ECB, CKM_SSF33_CBC_PAD};
  CK_BYTE_PTR bHint[3] = {(CK_BYTE_PTR) "CKM_SSF33_CBC: ",
                          (CK_BYTE_PTR) "CKM_SSF33_ECB: ",
                          (CK_BYTE_PTR) "CKM_SSF33_CBC_PAD: "};
  SHOW_INFO("\nSSF33: C_Encrypt/C_Decrypt: \n");
  do {
    for (int i = 0; i < 3; i++) {
      for (i != 2 ? ulIn = SSF33_BLOCK_LEN : ulIn = 0; ulIn < 32;
           i != 2 ? ulIn += SSF33_BLOCK_LEN : ++ulIn) {
        for (register CK_ULONG i0 = 0; i0 < ulIn; i0++) bIn[i0] = (CK_BYTE)i0;

        SHOW_INFO("\n********************************\n");
        SHOW_INFO(bHint[i]);
        // ecnrypt init:
        CK_BYTE iv[16] = {'*', '2', '1', '0', '4', 'z', 'y', 'b',
                          '*', '2', '1', '0', '4', 'z', 'y', 'b'};
        CK_MECHANISM ckMechanism = {Mechanism[i], iv, 16};
        START_OP("Encrypting initialize.")
        CK_RV rv = m_gToken->C_EncryptInit(hSession, &ckMechanism, m_hKey);
        CHECK_OP(rv)

        START_OP("Encrypt the message.")
        // Get the encrypted buffer's size:
        //{{{Here, I do not invoke "C_Encrypt" twice for I had declared bTemp
        //with a size=1024.
        // If you do not declare the result's buffer previous,
        // you should invoke twice to get the buffer's size, such as:[Decrypt is
        // similar]
        rv = m_gToken->C_Encrypt(hSession, bIn, ulIn, NULL, &ulTemp);
        //}}}
        CHECK_RV("C_Encrypt[get buffer's size]", rv);
        // encrypt:
        rv = m_gToken->C_Encrypt(hSession, bIn, ulIn, bTemp, &ulTemp);
        CHECK_RV("C_Encrypt", rv);
        CHECK_OP(rv);
        SHOW_INFO("Data encrypted: \n");
        ShowData(bTemp, ulTemp);

        START_OP("Decrypting initialize.");
        rv = m_gToken->C_DecryptInit(hSession, &ckMechanism, m_hKey);
        CHECK_OP(rv);
        START_OP("Decrypt the message.");
        // Get buffer's size:
        rv = m_gToken->C_Decrypt(hSession, bTemp, ulTemp, NULL, &ulOut);
        // Get decrypted data:
        rv = m_gToken->C_Decrypt(hSession, bTemp, ulTemp, bOut, &ulOut);
        CHECK_OP(rv);
        SHOW_INFO("Data decrypted: \n");
        ShowData(bOut, ulOut);

        START_OP("Compare the original message and decrypted data: ");
        if (0 == memcmp(bIn, bOut, ulOut)) {
          CHECK_OP(CKR_OK);
        } else {
          SHOW_INFO("....[FAILED]\n");
        }
      }
    }
  } while (0);
}

void Ssf33Test::crypt_Update() {
  const CK_ULONG DATA_LENGTH = 1024 * 3;
  CK_BYTE bIn[DATA_LENGTH] = {0}, bTemp[DATA_LENGTH] = {0},
          bOut[DATA_LENGTH] = {0};
  CK_ULONG ulIn = 0, ulOut = 0, ulTemp = 0;
  CK_ULONG Mechanism[3] = {CKM_SSF33_CBC, CKM_SSF33_ECB, CKM_SSF33_CBC_PAD};
  CK_BYTE_PTR bHint[3] = {(CK_BYTE_PTR) "CKM_SSF33_CBC: ",
                          (CK_BYTE_PTR) "CKM_SSF33_ECB: ",
                          (CK_BYTE_PTR) "CKM_SSF33_CBC_PAD: "};
  SHOW_INFO("\n********************************\n");
  do {
    for (int i = 0; i < 3; i++) {
      for (i != 2 ? ulIn = SSF33_BLOCK_LEN : ulIn = 0; ulIn < 32;
           i != 2 ? ulIn += SSF33_BLOCK_LEN : ++ulIn) {
        for (register CK_ULONG i0 = 0; i0 < ulIn; i0++) bIn[i0] = (CK_BYTE)i0;

        SHOW_INFO("\n");
        SHOW_INFO("\nSSF33: C_EncryptUpdate/C_DecryptUpdate: \n");
        SHOW_INFO(bHint[i]);
        // ecnrypt init:
        CK_BYTE iv[16] = {'*', '2', '1', '0', '4', 'z', 'y', 'b',
                          '*', '2', '1', '0', '4', 'z', 'y', 'b'};
        CK_MECHANISM ckMechanism = {Mechanism[i], iv, sizeof(iv)};
        START_OP("Encrypting initialize.")
        CK_RV rv = m_gToken->C_EncryptInit(hSession, &ckMechanism, m_hKey);
        CHECK_OP(rv)

        CK_ULONG ulEncrypted = 0;
        START_OP("Encrypt the message.");

        unsigned long dwLoop = ulIn / BLOCK_SIZE;
        unsigned long dwLeft = ulIn % BLOCK_SIZE;
        unsigned long iii = 0;
        CK_BYTE_PTR pRetData = bTemp;
        for (iii = 0; iii < dwLoop; ++iii) {
          rv = m_gToken->C_EncryptUpdate(hSession, bIn + BLOCK_SIZE * iii,
                                         BLOCK_SIZE, NULL,
                                         &ulTemp);  // get buffer's size.
          rv = m_gToken->C_EncryptUpdate(hSession, bIn + BLOCK_SIZE * iii,
                                         BLOCK_SIZE, pRetData, &ulTemp);
          pRetData += ulTemp;
          ulEncrypted += ulTemp;
          CHECK_RV("C_Encrypt[inside loop]", rv);
        }
        if (0 != dwLeft) {
          rv = m_gToken->C_EncryptUpdate(hSession, bIn + BLOCK_SIZE * iii,
                                         dwLeft, NULL,
                                         &ulTemp);  // get buffer's size.
          rv = m_gToken->C_EncryptUpdate(hSession, bIn + BLOCK_SIZE * iii,
                                         dwLeft, pRetData, &ulTemp);
          pRetData += ulTemp;
          ulEncrypted += ulTemp;
          CHECK_RV("C_Encrypt[last block]", rv);
        }

        START_OP("C_EncryptFinal...");
        rv = m_gToken->C_EncryptFinal(hSession, NULL, &ulTemp);
        rv = m_gToken->C_EncryptFinal(hSession, pRetData, &ulTemp);
        CHECK_OP(rv);
        ulEncrypted += ulTemp;
        ulTemp = 0;
        SHOW_INFO("Data encrypted: \n");
        ShowData(bTemp, ulEncrypted);

        //-------------------------------------------------------------------------//

        START_OP("Decrypting initialize.");
        CK_BYTE iv1[16] = {'*', '2', '1', '0', '4', 'z', 'y', 'b',
                           '*', '2', '1', '0', '4', 'z', 'y', 'b'};
        CK_MECHANISM ckMechanism1 = {Mechanism[i], iv1, sizeof(iv1)};
        rv = m_gToken->C_DecryptInit(hSession, &ckMechanism1, m_hKey);
        CHECK_OP(rv);
        START_OP("Decrypt the message.");

        dwLoop = ulEncrypted / DEC_BLOCK_SIZE;
        //			dwLeft = ulEncrypted % DEC_BLOCK_SIZE;

        iii = 0;
        pRetData = bOut;
        CK_ULONG ulDecrypt = 0;
        for (iii = 0; iii < dwLoop; ++iii) {
          rv = m_gToken->C_DecryptUpdate(hSession, bTemp + DEC_BLOCK_SIZE * iii,
                                         DEC_BLOCK_SIZE, NULL,
                                         &ulTemp);  // get buffer's size.
          rv = m_gToken->C_DecryptUpdate(hSession, bTemp + DEC_BLOCK_SIZE * iii,
                                         DEC_BLOCK_SIZE, pRetData, &ulTemp);
          pRetData += ulTemp;
          ulDecrypt += ulTemp;
          CHECK_RV("C_Decrypt[inside loop]", rv);
        }
        START_OP("C_DecryptFinale...");
        rv = m_gToken->C_DecryptFinal(hSession, NULL, &ulTemp);
        rv = m_gToken->C_DecryptFinal(hSession, pRetData, &ulTemp);
        CHECK_OP(rv);
        ulDecrypt += ulTemp;

        SHOW_INFO("Data decrypted: \n");
        ShowData(bOut, ulDecrypt);

        START_OP("Compare the original message and decrypted data: ");
        if (0 == memcmp(bIn, bOut, ulDecrypt)) {
          CHECK_OP(CKR_OK);
        } else {
          SHOW_INFO("....[FAILED]\n");
        }
      }
    }
  } while (0);
}
